package driver

import (
	"fmt"
	"gitee.com/xluomo945/fm/helper"
	"gitee.com/xluomo945/fm/setting"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	syslog "log"
	"time"
)

type model struct {
	Datetime time.Time
	Msg      string
	Level    string
	Trace    string
}

func (model) TableName() string {
	return "FM_LOGS"
}

type dbWriter struct {
	config      setting.LoggerConfig
	writer      *gorm.DB
	current     string
	isShowTrace bool
}

func (w *dbWriter) OpenTrace() {
	w.isShowTrace = true
}

// 检查句柄更新
func (w *dbWriter) isUpdateWriter() {
	if w.config.ByDay {
		current := name(w.config)
		if w.current != current {

			writer, err := createDBWriter(current)
			if err != nil {
				return
			}

			w.writer = writer
		}
	}
}

func (w *dbWriter) write(ctx *gin.Context, flag string, msg string) {
	w.isUpdateWriter()
	m := &model{Datetime: time.Now(), Msg: msg, Level: flag}
	if w.isShowTrace {
		m.Trace = trace(ctx)
	}
	w.writer.Create(m)
	w.console(ctx, flag, msg)
}

func (w *dbWriter) console(ctx *gin.Context, flag string, msg string) {
	if w.config.PrintConsole {
		if w.isShowTrace {
			syslog.Println(fmt.Sprintf("[%s][%s] %s", trace(ctx), flag, msg))
		} else {
			syslog.Println(fmt.Sprintf("[%s] %s", flag, msg))
		}
	}
}

func (w *dbWriter) Info(ctx *gin.Context, msg string) {
	w.write(ctx, "INFO", msg)
}

func (w *dbWriter) Warn(ctx *gin.Context, msg string) {
	w.write(ctx, "WARN", msg)
}

func (w *dbWriter) Fail(ctx *gin.Context, msg string) {
	w.write(ctx, "FAIL", msg)
}

func (w *dbWriter) Custom(ctx *gin.Context, flag string, msg string) {
	w.write(ctx, flag, msg)
}

func (w *dbWriter) Close() {}

func DBCreate(config setting.LoggerConfig) (setting.LogWriter, error) {
	if !helper.PathIsExists(config.Dir) {
		return nil, fmt.Errorf("model writer: Config dir is not exists. [%s]", config.Dir)
	}
	if helper.StringEmpty(config.Name) {
		syslog.Println("[Warn] model config name is empty. default name: log")
		config.Name = "log"
	}

	current := name(config)
	writer, err := createDBWriter(current)
	if err != nil {
		return nil, err
	}

	return &dbWriter{config: config, writer: writer, current: current}, nil
}

// 创建写入句柄
func createDBWriter(name string) (*gorm.DB, error) {
	writer, err := gorm.Open(sqlite.Open(name), &gorm.Config{})
	if err != nil {
		return nil, err
	}

	err = writer.AutoMigrate(&model{})
	if err != nil {
		return nil, err
	}

	return writer, nil
}
